package com.gcloud.mesh.dcs.strategy;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSONObject;
import com.gcloud.mesh.asset.dao.CloudResourceConfigDao;
import com.gcloud.mesh.asset.entity.CloudResourceConfigEntity;
import com.gcloud.mesh.dcs.dao.AppDao;
import com.gcloud.mesh.dcs.dao.SchedulerJobDao;
import com.gcloud.mesh.dcs.dao.SchedulerStepDao;
import com.gcloud.mesh.dcs.entity.AppEntity;
import com.gcloud.mesh.dcs.entity.SchedulerJobEntity;
import com.gcloud.mesh.dcs.entity.SchedulerStepEntity;
import com.gcloud.mesh.dcs.enums.SchedulerStepStatus;
import com.gcloud.mesh.dcs.strategy.huawei.BatchListMetricDataSolution;
import com.gcloud.mesh.dcs.strategy.huawei.CreateTaskSolution;
import com.gcloud.mesh.dcs.strategy.huawei.DeleteServersSolution;
import com.gcloud.mesh.dcs.strategy.huawei.ListServersDetailsSolution;
import com.gcloud.mesh.dcs.strategy.huawei.ShowServerDetailSolution;
import com.gcloud.mesh.dcs.strategy.huawei.ShowTaskSolution;
import com.gcloud.mesh.dcs.strategy.huawei.UpdateServerSolution;
import com.gcloud.mesh.dcs.strategy.huawei.UpdateTaskStatusSolution;
import com.gcloud.mesh.header.param.HuaweiMigrationParam;
import com.gcloud.mesh.header.vo.dcs.AppVo;
import com.gcloud.mesh.header.vo.dcs.DescribeMetricVO;
import com.gcloud.mesh.supplier.dao.SupplierDao;
import com.gcloud.mesh.supplier.entity.SupplierEntity;
import com.gcloud.mesh.supplier.enums.SystemType;
import com.gcloud.mesh.utils.DateUtil;
import com.google.common.collect.Lists;
import com.huaweicloud.sdk.ces.v1.model.BatchListMetricDataResponse;
import com.huaweicloud.sdk.ces.v1.model.BatchMetricData;
import com.huaweicloud.sdk.ecs.v2.model.ListServersDetailsResponse;
import com.huaweicloud.sdk.ecs.v2.model.ServerDetail;
import com.huaweicloud.sdk.ecs.v2.model.ShowServerResponse;
import com.huaweicloud.sdk.sms.v3.model.PostSourceServerBody;
import com.huaweicloud.sdk.sms.v3.model.ShowTaskResponse;
import com.huaweicloud.sdk.sms.v3.model.TargetDisks;

import lombok.extern.slf4j.Slf4j;

//@Component
@Slf4j
public class HuaweiMigrationStrategy implements ServerMigrationStrategy {
	

    @Autowired
    private SupplierDao supplierDao; 
    
    @Autowired
    private CreateTaskSolution createTaskSolution;
    
    @Autowired
    private UpdateTaskStatusSolution updateTaskStatusSolution;
    
    @Autowired
    private ShowTaskSolution showTaskSolution;
    
    @Autowired
    private SchedulerStepDao schedulerStepDao;
    
    @Autowired
    private DeleteServersSolution deleteServersSolution;
    
    @Autowired
    private SchedulerJobDao schedulerJobDao;
    
    @Autowired
    private CloudResourceConfigDao cloudResourceConfigDao;
    
    
    @Autowired
    private UpdateServerSolution updateServersSolution;

    @Autowired
    private AppDao appDao;
    
    @Override
    public Object doMigration(Serializable p) {
        HuaweiMigrationParam huaweiMigrationParam = JSONObject.toJavaObject((JSONObject)p,HuaweiMigrationParam.class);
        //创建迁移任务ID
        log.info("begin huawei migrate vm :: 开始华为云迁移");
        String sourceServerId = createTaskSolution.getSourceServerId(huaweiMigrationParam.getMyJobId(), huaweiMigrationParam.getAccessKey(), huaweiMigrationParam.getSecretKey(), huaweiMigrationParam.getVmName());
        log.info("任务获取迁移的源资源id是"+sourceServerId);
        List<TargetDisks> disk = createTaskSolution.getTargetDisk(huaweiMigrationParam.getMyJobId(), huaweiMigrationParam.getAccessKey(), huaweiMigrationParam.getSecretKey(), sourceServerId);
        log.info("获取源磁盘成功");
        String taskId = createTaskSolution.createTask(huaweiMigrationParam.getMyJobId(), huaweiMigrationParam.getAccessKey(), huaweiMigrationParam.getSecretKey(), huaweiMigrationParam.getVmName(), huaweiMigrationParam.getDestRegionId(), disk, sourceServerId);
        log.info("task huawei migrate vm :: 创建华为云迁移任务："+String.valueOf(taskId));
        //执行迁移
        updateTaskStatusSolution.updateTaskStatus(huaweiMigrationParam.getMyJobId(), huaweiMigrationParam.getAccessKey(), huaweiMigrationParam.getSecretKey(), taskId, "start");
        log.info("huawei migrating vm :: 华为云迁移任务执行成功："+String.valueOf(taskId));
        //监听任务状态
        SchedulerStepEntity sse = new SchedulerStepEntity();
        sse.setBeginTime(new Date());
        sse.setId(UUID.randomUUID().toString());
        sse.setName("检查迁移进度");
        sse.setSchedulerJobId(huaweiMigrationParam.getMyJobId());
        sse.setStatus(SchedulerStepStatus.PROGRESS.getValue());
        JSONObject attach = new JSONObject();
        attach.put("accessKeyId",huaweiMigrationParam.getAccessKey());
        attach.put("accessSecret",huaweiMigrationParam.getSecretKey());
        attach.put("regionId", huaweiMigrationParam.getRegionId());
        attach.put("targetRegionId", huaweiMigrationParam.getDestRegionId());
        //attach。put("instanceId", i)
        attach.put("jobId", huaweiMigrationParam.getMyJobId());
        attach.put("appName", huaweiMigrationParam.getVmName());
        attach.put("taskId",taskId);
        sse.setAttach(attach.toString());
        sse.setSchedulerType(SystemType.HUAWEI.getName());
        sse.setStepNo(1);
        schedulerStepDao.save(sse);
        return null;
    }

    @Override
    public String getStrategyName() {
        return SystemType.HUAWEI.getName();
    }

	@Override
	public Boolean checkStatus(Integer stepNo, String attach) {
        JSONObject json = JSONObject.parseObject(attach);
        String accessKeyId = json.getString("accessKeyId");
        String accessSecret = json.getString("accessSecret");
        String taskId = json.getString("taskId");
        String regionId = json.getString("regionId");
        String targetRegionId = json.getString("targetRegionId");
        String appName = json.getString("appName");
        String jobId = json.getString("jobId");
        ShowTaskResponse res = showTaskSolution.showTask(accessKeyId, accessSecret, taskId);
        PostSourceServerBody sourceServer = res.getSourceServer();
        //获取所有迁移进程,当最后一个进程结束调用启动目标端
        if("syncing".equals(sourceServer.getState())) {
        	 updateTaskStatusSolution.updateTaskTest(jobId, accessKeyId, accessSecret, taskId, "test");
        }
        Long date = res.getFinishDate();
      
        if(date != null) {
        	//删除源虚拟机etc
        	Map<String, Object> param = new HashMap<>();
        	param.put("name", appName);
        	 AppEntity appen = appDao.findUniqueByProperties(param);
        	 log.info("删除源虚拟机，参数"+jobId+":"+accessKeyId+":"+accessSecret+":"+regionId+":"+appen.getId());
         	//找不到源虚拟机返回true
         	ShowServerDetailSolution show = new ShowServerDetailSolution();
            ShowServerResponse resp = show.showServer(accessKeyId, accessSecret, regionId, appen.getId());
        	log.info("查询源虚拟机返回是"+resp);
            if(resp != null && resp.getServer() != null && !resp.getServer().getStatus().equalsIgnoreCase("DELETED")) {
            	try {
    				deleteServersSolution.deleteServers(jobId, accessKeyId, accessSecret, regionId, appen.getId());
    			} catch (Exception e) {
    				log.error("删除源虚拟机失败:"+e);
    				return false;
    			}
            }
            if(resp == null || resp.getServer() == null || resp.getServer().getStatus().equalsIgnoreCase("DELETED")) {
            	//删除源虚拟机
            	SchedulerJobEntity job = schedulerJobDao.getById(jobId);
            	job.setAppId(res.getTargetServer().getVmId());
            	schedulerJobDao.update(job);
            	appDao.delete(appen);
            	//替换appId
            	appen.setId(res.getTargetServer().getVmId());
            	updateServersSolution.updateServer(jobId, accessKeyId, accessSecret, res.getTargetServer().getVmId(), appName, targetRegionId);
            	appDao.save(appen);
            	return true;
            }
        }
        return false;
        
	}

	@Override
	public List<AppEntity> queryServerList(String cloudResourceId) {
		
		
        // SupplierEntity supplierEntity = supplierDao.findOneByProperty("datacenter_id", datacenterId);
		CloudResourceConfigEntity cloudResource = cloudResourceConfigDao.findOneByProperty("cloud_resource_id", cloudResourceId);
        if(cloudResource==null) return Lists.newArrayList();

        HuaweiMigrationParam aliMigrationParam = JSONObject.toJavaObject(JSONObject.parseObject(cloudResource.getConfig()), HuaweiMigrationParam.class);

        List<AppEntity> list = new ArrayList<>();
        ListServersDetailsSolution listServer = new ListServersDetailsSolution();
        ListServersDetailsResponse response = listServer.listServers(aliMigrationParam.getRegionId(), aliMigrationParam.getAccessKey(), aliMigrationParam.getSecretKey(), aliMigrationParam.getProjectId());
        List<ServerDetail>  lists =  response.getServers();
        if(response != null && !response.getServers().isEmpty()) {
        	for(ServerDetail detail : lists) {
            	AppEntity en = new AppEntity();
            	// en.setCloudResourceId(detail.getId());
            	en.setId(detail.getId());
            	en.setName(detail.getName());
            	en.setCreateTime(DateUtil.stringToDate(detail.getCreated()));
            	list.add(en);
        	}

        }
		return list;
	}

	@Override
	public List<DescribeMetricVO> queryDescribeMetricLastList(String datacenterId) {
        List<AppVo> appList = appDao.getByDatacenterId(datacenterId);
    	long from = System.currentTimeMillis()-60000;//60秒钟检查一次
    	long to = System.currentTimeMillis();
        // Map<String,String> appMap = Maps.newHashMap();
        SupplierEntity supplierEntity = supplierDao.findOneByProperty("datacenterId", datacenterId);
        HuaweiMigrationParam huaweiMigrationParam = JSONObject.toJavaObject(JSONObject.parseObject(supplierEntity.getConfig()), HuaweiMigrationParam.class);
        String accessKeyId = huaweiMigrationParam.getAccessKey();
        String accessKeySecret = huaweiMigrationParam.getSecretKey();
        String regionId = huaweiMigrationParam.getRegionId();
        BatchListMetricDataSolution listMetric = new BatchListMetricDataSolution();
        List<DescribeMetricVO> vos = new ArrayList<>();
        if(appList!=null && !appList.isEmpty()){
        	for(AppVo app : appList) {
                if(supplierEntity!=null){
                	Double mem = 0.0;
                	Double cpu = 0.0;
                	BatchListMetricDataResponse res = listMetric.listMetricData(app.getId(), regionId, accessKeyId, accessKeySecret, from, to);
                	List<BatchMetricData>  datas = res.getMetrics();
                	if(res.getMetrics() != null) {
                		DescribeMetricVO vo = new DescribeMetricVO();
                		vo.setInstanceId(app.getId());
                		vo.setInstanceName(app.getName());
                		vo.setMemVal("0");
                		vo.setCupVal("0");
                		for(BatchMetricData data : datas) {
                			if("mem_usedPercent".equals(data.getMetricName())) {
                				if(data.getDatapoints()!= null && !data.getDatapoints().isEmpty()) {
                					// log.info("监控项[HUAWEI_MEM_UTIL] menVal: {}",data.getDatapoints().get(0).getAverage());
                					mem =  data.getDatapoints().get(0).getAverage();
                					vo.setMemVal((mem == null ? "0.0":String.valueOf(mem)));
                				}
                			}
                			if("cpu_util".equals(data.getMetricName())) {
                				if(data.getDatapoints()!= null && !data.getDatapoints().isEmpty()) {
                					cpu =  data.getDatapoints().get(0).getAverage();
                					vo.setCupVal((cpu == null ? "0.0":String.valueOf(cpu)));
                				}
                			}
                			
                		}
                		vos.add(vo);
                	}

                }
        	}
           


        }

        return vos;
	}
	
	
    
}
